package com.java.jvm.loader;

import java.io.*;

/**
 * ClassLoader没有抽象方法为什么还要将此类定义为抽象类？外界不允许直接构建此类对象
 */
public class DefaultAppClassLoader extends ClassLoader{

    private String baseDir;

    public DefaultAppClassLoader(String baseDir) {
        this.baseDir = baseDir;
    }
    /**
     * 查找类
     * @param className 类全名 (eg,com.java.jvm.HelloJVM)
     * @return 返回值为字节码对象(这就说明了一个问题，类加载时字节码对象就创建了)
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String className) throws ClassNotFoundException {
        //1.基于类名读取类(从磁盘指定路径下找到对应的类，并基于io对内容进行读取)，并将信息存储到字节数组。
        byte[] data=readClassInfo(className);
        //2.将字节数组中的信息转换字节码对象
        if(data==null||data.length==0)
            throw new ClassNotFoundException();
        return defineClass(className, data,0 , data.length);
    }
    /**
     * 读取字节码信息
     * @param className
     * @return
     */
    private byte[] readClassInfo(String className){
        //1.获取className的绝对路径
        String absFilePath=baseDir+className.replace('.', File.separatorChar)+".class";
        //2.判定文件是否存在
        InputStream in=null;
        File file=new File(absFilePath);
        try {
            if (!file.exists()) throw new FileNotFoundException();
            //3.构建流对象
            in = new FileInputStream(file);
            //4.读数据并返回
            byte[] data = new byte[in.available()];
            in.read(data);
            return data;
        }catch (IOException ex){
            ex.printStackTrace();
            throw new RuntimeException("文件不存在或读取失败");
        }finally {
            //5.释放资源
            if(in!=null)try{in.close();}catch (Exception e){e.printStackTrace();}
        }
    }
}
